home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / Filezilla Server / FileZilla_Server-0_9_41.exe / source / ServerThread.cpp < prev    next >
C/C++ Source or Header  |  2012-02-20  |  27KB  |  954 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // ServerThread.cpp: Implementierungsdatei
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "iputils.h"
  24. #include "ServerThread.h"
  25. #include "ControlSocket.h"
  26. #include "transfersocket.h"
  27. #include "Options.h"
  28. #include "version.h"
  29. #include "Permissions.h"
  30. #include "ExternalIpCheck.h"
  31. #include "autobanmanager.h"
  32. #include "hash_thread.h"
  33.  
  34. #ifdef _DEBUG
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38.  
  39. std::map<int, t_socketdata> CServerThread::m_userids;
  40. CCriticalSectionWrapper CServerThread::m_GlobalThreadsync;
  41. std::map<CStdString, int> CServerThread::m_userIPs;
  42. std::list<CServerThread*> CServerThread::m_sInstanceList;
  43. std::map<CStdString, int> CServerThread::m_antiHammerInfo;
  44. CHashThread* CServerThread::m_hashThread = 0;
  45.  
  46. /////////////////////////////////////////////////////////////////////////////
  47. // CServerThread
  48.  
  49. CServerThread::CServerThread(int nNotificationMessageId)
  50. {
  51.     m_nNotificationMessageId = nNotificationMessageId;
  52.     m_pOptions = 0;
  53.     m_pAutoBanManager = 0;
  54. }
  55.  
  56. CServerThread::~CServerThread()
  57. {
  58. }
  59.  
  60. BOOL CServerThread::InitInstance()
  61. {
  62.     BOOL res = TRUE;
  63.     WSADATA wsaData;
  64.     
  65.     WORD wVersionRequested = MAKEWORD(1, 1);
  66.     int nResult = WSAStartup(wVersionRequested, &wsaData);
  67.     if (nResult != 0)
  68.         res=FALSE;
  69.     else if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
  70.     {
  71.         WSACleanup();
  72.         res=FALSE;
  73.     }
  74.     
  75.     m_timerid = SetTimer(0, 0, 1000, 0);
  76.     m_nRateTimer = SetTimer(0, 0, 100, 0);
  77.  
  78.     // Reduce anti hammer value twice an hour
  79.     m_antiHammerTimer = SetTimer(0, 0, 1800 * 1000, 0);
  80.  
  81.     m_bQuit = FALSE;
  82.     m_nRecvCount = 0;
  83.     m_nSendCount = 0;
  84.     m_pOptions = new COptions;
  85.     m_pAutoBanManager = new CAutoBanManager(m_pOptions);
  86.     m_pPermissions = new CPermissions;
  87.  
  88.     EnterCritSection(m_GlobalThreadsync);
  89.     if (m_sInstanceList.empty())
  90.         m_bIsMaster = TRUE;
  91.     else
  92.         m_bIsMaster = FALSE;
  93.     m_sInstanceList.push_back(this);
  94.     LeaveCritSection(m_GlobalThreadsync);
  95.  
  96.     m_nLoopCount = 0;
  97.  
  98.     EnterCritSection(m_threadsync);
  99.     if (!m_bIsMaster)
  100.         m_pExternalIpCheck = NULL;
  101.     else
  102.     {
  103.         m_pExternalIpCheck = new CExternalIpCheck(this);
  104.         m_hashThread = new CHashThread();
  105.     }
  106.     LeaveCritSection(m_threadsync);
  107.  
  108.     m_throttled = 0;
  109.  
  110.     return TRUE;
  111. }
  112.  
  113. DWORD CServerThread::ExitInstance()
  114. {
  115.     ASSERT(m_pPermissions);
  116.     delete m_pPermissions;
  117.     m_pPermissions=0;
  118.     delete m_pAutoBanManager;
  119.     m_pAutoBanManager = 0;
  120.     delete m_pOptions;
  121.     m_pOptions=0;
  122.     KillTimer(0, m_timerid);
  123.     KillTimer(0, m_nRateTimer);
  124.     WSACleanup();
  125.     m_hashThread->Stop(this);
  126.  
  127.     if (m_bIsMaster)
  128.     {
  129.         EnterCritSection(m_threadsync);
  130.         delete m_pExternalIpCheck;
  131.         m_pExternalIpCheck = NULL;
  132.         LeaveCritSection(m_threadsync);
  133.     }
  134.  
  135.     EnterCritSection(m_GlobalThreadsync);
  136.     m_sInstanceList.remove(this);
  137.     if (!m_sInstanceList.empty())
  138.         m_sInstanceList.front()->m_bIsMaster = TRUE;
  139.     else
  140.     {
  141.         delete m_hashThread;
  142.         m_hashThread = 0;
  143.     }
  144.     LeaveCritSection(m_GlobalThreadsync);
  145.  
  146.     return 0;
  147. }
  148.  
  149. /////////////////////////////////////////////////////////////////////////////
  150. // Behandlungsroutinen fⁿr Nachrichten CServerThread 
  151.  
  152. const int CServerThread::GetNumConnections()
  153. {
  154.     EnterCritSection(m_threadsync);
  155.     int num = m_LocalUserIDs.size();
  156.     LeaveCritSection(m_threadsync);
  157.     return num;
  158. }
  159.  
  160. void CServerThread::AddSocket(SOCKET sockethandle, bool ssl)
  161. {
  162.     PostThreadMessage(WM_FILEZILLA_THREADMSG, ssl ? FTM_NEWSOCKET_SSL : FTM_NEWSOCKET, (LPARAM)sockethandle);
  163. }
  164.  
  165. #define IDMAX 1000000000
  166. int CServerThread::CalcUserID()
  167. {
  168.     if (m_userids.size() >= IDMAX)
  169.         return -1;
  170.     static int curid=0;
  171.     curid++;
  172.     if (curid==IDMAX)
  173.         curid=1;
  174.     while (m_userids.find(curid) != m_userids.end())
  175.     {
  176.         curid++;
  177.         if (curid == IDMAX)
  178.             curid=1;
  179.     }
  180.     return curid;
  181. }
  182.  
  183. void CServerThread::AddNewSocket(SOCKET sockethandle, bool ssl)
  184. {
  185.     CControlSocket *socket = new CControlSocket(this);
  186.     if (!socket->Attach(sockethandle))
  187.     {
  188.         socket->SendStatus(_T("Failed to attach socket."), 1);
  189.         closesocket(sockethandle);
  190.         return;
  191.     }
  192.  
  193.     CStdString ip;
  194.     UINT port = 0;
  195.     if (socket->GetPeerName(ip, port))
  196.     {
  197.         if (socket->GetFamily() == AF_INET6)
  198.             ip = GetIPV6ShortForm(ip);
  199.         socket->m_RemoteIP = ip;
  200.     }
  201.     else
  202.     {
  203.         socket->m_RemoteIP = _T("ip unknown");
  204.         socket->m_userid = 0;
  205.         socket->SendStatus(_T("Can't get remote IP, disconnected"), 1);
  206.         socket->Close();
  207.         delete socket;
  208.         return;
  209.     }
  210.     EnterCritSection(m_GlobalThreadsync);
  211.     int userid = CalcUserID();
  212.     if (userid == -1)
  213.     {
  214.         LeaveCritSection(m_GlobalThreadsync);
  215.         socket->m_userid = 0;
  216.         socket->SendStatus(_T("Refusing connection, server too busy!"), 1);
  217.         socket->Send(_T("421 Server too busy, closing connection. Please retry later!"));
  218.         socket->Close();
  219.         delete socket;
  220.         return;
  221.     }
  222.     socket->m_userid = userid;
  223.     t_socketdata data;
  224.     data.pSocket = socket;
  225.     data.pThread = this;
  226.     m_userids[userid] = data;
  227.  
  228.     // Check if remote IP is blocked due to hammering
  229.     std::map<CStdString, int>::const_iterator iter = m_antiHammerInfo.find(ip);
  230.     if (iter != m_antiHammerInfo.end() && iter->second > 10)
  231.         socket->AntiHammerIncrease(25); // ~6 secs delay
  232.     LeaveCritSection(m_GlobalThreadsync);
  233.     EnterCritSection(m_threadsync);
  234.     m_LocalUserIDs[userid] = socket;
  235.     LeaveCritSection(m_threadsync);
  236.  
  237.     t_connectiondata_add *conndata = new t_connectiondata_add;
  238.     t_connop *op = new t_connop;
  239.     op->data = conndata;
  240.     op->op = USERCONTROL_CONNOP_ADD;
  241.     op->userid = userid;
  242.     conndata->pThread = this;
  243.  
  244.     conndata->port = port;
  245.     _tcscpy(conndata->ip, socket->m_RemoteIP);
  246.  
  247.     SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  248.  
  249.     if (ssl && !socket->InitImplicitSsl())
  250.         return;
  251.  
  252.     socket->AsyncSelect(FD_READ|FD_WRITE|FD_CLOSE);
  253.     socket->SendStatus(_T("Connected, sending welcome message..."), 0);
  254.  
  255.     CStdString msg;
  256.     if (m_pOptions->GetOptionVal(OPTION_ENABLE_HASH))
  257.         msg = _T("EXPERIMANTAL BUILD\nNOT FOR PRODUCTION USE\n\nImplementing draft-bryan-ftp-hash-06");
  258.     else
  259.         msg = m_pOptions->GetOption(OPTION_WELCOMEMESSAGE);
  260.     if (m_RawWelcomeMessage != msg)
  261.     {
  262.         m_RawWelcomeMessage = msg;
  263.         m_ParsedWelcomeMessage.clear();
  264.  
  265.         msg.Replace(_T("%%"), _T("\001"));
  266.         msg.Replace(_T("%v"), GetVersionString());
  267.         msg.Replace(_T("\001"), _T("%"));
  268.  
  269.         ASSERT(msg != _T(""));
  270.         int oldpos = 0;
  271.         msg.Replace(_T("\r\n"), _T("\n"));
  272.         int pos = msg.Find(_T("\n"));
  273.         CStdString line;
  274.         while (pos != -1)
  275.         {
  276.             ASSERT(pos);
  277.             m_ParsedWelcomeMessage.push_back(_T("220-") +  msg.Mid(oldpos, pos-oldpos) );
  278.             oldpos = pos + 1;
  279.             pos = msg.Find(_T("\n"), oldpos);
  280.         }
  281.  
  282.         line = msg.Mid(oldpos);
  283.         if (line != _T(""))
  284.             m_ParsedWelcomeMessage.push_back(_T("220 ") + line);        
  285.         else
  286.         {
  287.             m_ParsedWelcomeMessage.back()[3] = 0;
  288.         }
  289.     }
  290.  
  291.     bool hideStatus = m_pOptions->GetOptionVal(OPTION_WELCOMEMESSAGE_HIDE) != 0;
  292.     ASSERT(!m_ParsedWelcomeMessage.empty());
  293.     for (std::list<CStdString>::iterator iter = m_ParsedWelcomeMessage.begin(); iter != m_ParsedWelcomeMessage.end(); iter++)
  294.         if (!socket->Send(*iter, !hideStatus))
  295.             break;
  296. }
  297.  
  298. int CServerThread::OnThreadMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
  299. {
  300.     if (Msg == WM_FILEZILLA_THREADMSG)
  301.     {
  302.         if (wParam == FTM_NEWSOCKET) //Add a new socket to this thread
  303.             AddNewSocket((SOCKET)lParam, false);
  304.         else if (wParam == FTM_NEWSOCKET_SSL) //Add a new socket to this thread
  305.             AddNewSocket((SOCKET)lParam, true);
  306.         else if (wParam==FTM_DELSOCKET) //Remove a socket from this thread
  307.         {
  308.             CControlSocket *socket=GetControlSocket(lParam);
  309.             EnterCritSection(m_threadsync);
  310.             if (m_LocalUserIDs.find(lParam)!=m_LocalUserIDs.end())
  311.                 m_LocalUserIDs.erase(m_LocalUserIDs.find(lParam));
  312.             LeaveCritSection(m_threadsync);
  313.             if (socket)
  314.             {
  315.                 socket->Close();
  316.                 EnterCritSection(m_GlobalThreadsync);
  317.                 if (m_userids.find(lParam)!=m_userids.end())
  318.                     m_userids.erase(m_userids.find(lParam));
  319.                 LeaveCritSection(m_GlobalThreadsync);
  320.                 delete socket;
  321.             }
  322.             EnterCritSection(m_threadsync);
  323.             if (m_bQuit)
  324.             {
  325.                 int count=m_LocalUserIDs.size();
  326.                 LeaveCritSection(m_threadsync);
  327.                 if (!count)
  328.                     SendNotification(FSM_THREADCANQUIT, (LPARAM)this);
  329.             }
  330.             else
  331.                 LeaveCritSection(m_threadsync);
  332.         }
  333.         else if (wParam==FTM_COMMAND)
  334.         { //Process a command sent from a client
  335.             CControlSocket *socket=GetControlSocket(lParam);
  336.             if (socket)
  337.                 socket->ParseCommand();
  338.         }
  339.         else if (wParam==FTM_TRANSFERMSG)
  340.         {
  341.             CControlSocket *socket=GetControlSocket(lParam);
  342.             if (socket)
  343.                 socket->ProcessTransferMsg();
  344.         }
  345.         else if (wParam==FTM_GOOFFLINE)
  346.         {
  347.             EnterCritSection(m_threadsync);
  348.             m_bQuit = TRUE;
  349.             int count = m_LocalUserIDs.size();
  350.             if (!count)
  351.             {
  352.                 LeaveCritSection(m_threadsync);
  353.                 SendNotification(FSM_THREADCANQUIT, (LPARAM)this);
  354.                 return 0;
  355.             }
  356.             if (lParam==2)
  357.             {
  358.                 LeaveCritSection(m_threadsync);
  359.                 return 0;
  360.             }
  361.             for (std::map<int, CControlSocket *>::iterator iter=m_LocalUserIDs.begin(); iter!=m_LocalUserIDs.end(); iter++)
  362.             {
  363.                 switch (lParam)
  364.                 {
  365.                 case 2:
  366.                     iter->second->WaitGoOffline(false);
  367.                     break;
  368.                 case 0:
  369.                 default:
  370.                     iter->second->ForceClose(0);
  371.                     break;
  372.                 case 1:
  373.                     iter->second->WaitGoOffline(true);
  374.                     break;
  375.                 }
  376.             }
  377.             LeaveCritSection(m_threadsync);
  378.         }
  379.         else if (wParam == FTM_CONTROL)
  380.             ProcessControlMessage((t_controlmessage *)lParam);
  381.         else if (wParam == FTM_HASHRESULT)
  382.         {
  383.             CHashThread::_algorithm alg;
  384.             CStdString hash;
  385.             CStdString file;
  386.             int hash_res = GetHashThread().GetResult(lParam, alg, hash, file);
  387.             EnterCritSection(m_threadsync);
  388.  
  389.             for (std::map<int, CControlSocket *>::iterator iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  390.             {
  391.                 iter->second->ProcessHashResult(lParam, hash_res, alg, hash, file);
  392.             }
  393.             LeaveCritSection(m_threadsync);
  394.         }
  395.     }
  396.     else if (Msg == WM_TIMER)
  397.         OnTimer(wParam, lParam);
  398.     return 0;
  399. }
  400.  
  401. void CServerThread::OnTimer(WPARAM wParam,LPARAM lParam)
  402. {
  403.     if (wParam == m_timerid)
  404.     {
  405.         EnterCritSection(m_threadsync);
  406.         
  407.         /* 
  408.          * Check timeouts and collect transfer file offsets.
  409.          * Do both in the same loop to save performance.
  410.          */
  411.  
  412.         /*
  413.          * Maximum memory required for file offsets:
  414.          * 2 unused prefix bytes, will be filled by CServer,
  415.          * This avoids buffer copying.
  416.          * For each connection 4 bytes for the userid
  417.          * and 8 for the offset.
  418.          * We do not need to store the number of elements, this
  419.          * information can be calculated from the length if neccessary.
  420.          */
  421.         int bufferLen = 2 + m_LocalUserIDs.size() * 12;
  422.         unsigned char* buffer = new unsigned char[bufferLen];
  423.         unsigned char* p = buffer + 2;
  424.         for (std::map<int, CControlSocket *>::iterator iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  425.         {
  426.             CControlSocket* pSocket = iter->second;
  427.             CTransferSocket* pTransferSocket = pSocket->GetTransferSocket();
  428.             if (pTransferSocket && pTransferSocket->WasActiveSinceCheck())
  429.             {
  430.                 memcpy(p, &iter->first, 4);
  431.                 p += 4;
  432.                 __int64 offset = pTransferSocket->GetCurrentFileOffset();
  433.                 memcpy(p, &offset, 8);
  434.                 p += 8;
  435.             }
  436.             iter->second->CheckForTimeout();
  437.         }
  438.         
  439.         if ((p - buffer) <= 2)
  440.             delete [] buffer;
  441.         else
  442.         {
  443.             t_connectiondata_transferoffsets* conndata = new t_connectiondata_transferoffsets;
  444.             conndata->pData = buffer;
  445.             conndata->len = p - buffer;
  446.             t_connop* op = new t_connop;
  447.             op->data = conndata;
  448.             op->op = USERCONTROL_CONNOP_TRANSFEROFFSETS;
  449.             SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  450.         }
  451.  
  452.         LeaveCritSection(m_threadsync);
  453.  
  454.         // Check if master thread has changed
  455.         if (m_bIsMaster && !m_pExternalIpCheck)
  456.         {
  457.             EnterCritSection(m_threadsync);
  458.             m_pExternalIpCheck = new CExternalIpCheck(this);
  459.             LeaveCritSection(m_threadsync);
  460.         }
  461.     }
  462.     else if (wParam==m_nRateTimer)
  463.     {
  464.         if (m_nSendCount)
  465.         {    
  466.             SendNotification(FSM_SEND, m_nSendCount);
  467.             m_nSendCount = 0;
  468.         }
  469.         if (m_nRecvCount)
  470.         {    
  471.             SendNotification(FSM_RECV, m_nRecvCount);
  472.             m_nRecvCount = 0;
  473.         }
  474.  
  475.         if (m_bIsMaster)
  476.         {
  477.             EnterCritSection(m_GlobalThreadsync);
  478.  
  479.             std::list<CServerThread *>::iterator iter;
  480.  
  481.             //Only update the speed limits from the rule set every 2 seconds to improve performance
  482.             if (!m_nLoopCount)
  483.             {
  484.                 m_lastLimits[download] = m_pOptions->GetCurrentSpeedLimit(download);
  485.                 m_lastLimits[upload] = m_pOptions->GetCurrentSpeedLimit(upload);
  486.             }
  487.             ++m_nLoopCount %= 20;
  488.  
  489.             // Gather transfer statistics if a speed limit is set
  490.             if (m_lastLimits[download] != -1 || m_lastLimits[upload] != -1)
  491.                 for (iter = m_sInstanceList.begin(); iter != m_sInstanceList.end(); iter++)
  492.                 {
  493.                     CServerThread *pThread = *iter;
  494.                     EnterCritSection(pThread->m_threadsync);
  495.                     pThread->GatherTransferedBytes();
  496.                     LeaveCritSection(pThread->m_threadsync);
  497.                 }
  498.  
  499.             for (int i = 0; i < 2; i++)
  500.             {
  501.                 long long limit = m_lastLimits[i];
  502.  
  503.                 if (limit == -1)
  504.                 {
  505.                     for (iter = m_sInstanceList.begin(); iter != m_sInstanceList.end(); iter++)
  506.                     {
  507.                         CServerThread *pThread = *iter;
  508.                         EnterCritSection(pThread->m_threadsync);
  509.                         pThread->m_SlQuotas[i].nBytesAllowedToTransfer = -1;
  510.                         pThread->m_SlQuotas[i].nTransferred = 0;
  511.                         LeaveCritSection(pThread->m_threadsync);
  512.                     }
  513.                     continue;
  514.                 }
  515.  
  516.                 limit *= 100;
  517.                 
  518.                 long long nRemaining = limit;
  519.                 long long nThreadLimit = limit / m_sInstanceList.size();
  520.                 
  521.                 std::list<CServerThread *> fullUsageList;
  522.                 
  523.                 for (iter = m_sInstanceList.begin(); iter != m_sInstanceList.end(); iter++)
  524.                 {
  525.                     CServerThread *pThread = *iter;
  526.                     EnterCritSection(pThread->m_threadsync);
  527.                     long long r = pThread->m_SlQuotas[i].nBytesAllowedToTransfer - pThread->m_SlQuotas[i].nTransferred;
  528.                     if ( r > 0 && pThread->m_SlQuotas[i].nBytesAllowedToTransfer <= nThreadLimit)
  529.                     {
  530.                         pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  531.                         nRemaining -= pThread->m_SlQuotas[i].nTransferred;
  532.                         pThread->m_SlQuotas[i].nTransferred = 0;
  533.                     }
  534.                     else if (r > 0 && pThread->m_SlQuotas[i].nTransferred < nThreadLimit)
  535.                     {
  536.                         pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  537.                         nRemaining -= pThread->m_SlQuotas[i].nTransferred;
  538.                         pThread->m_SlQuotas[i].nTransferred = 0;
  539.                     }
  540.                     else
  541.                     {
  542.                         fullUsageList.push_back(pThread);
  543.                         // Don't unlock thread here, do it later
  544.                         continue;
  545.                     }
  546.                     LeaveCritSection(pThread->m_threadsync);
  547.                 }
  548.                 
  549.                 // fullUsageList now contains all threads which did use up its assigned quota
  550.                 std::list<CServerThread *> fullUsageList2;
  551.                 if (!fullUsageList.empty())
  552.                 {
  553.                     nThreadLimit = nRemaining / fullUsageList.size();
  554.                     for (iter = fullUsageList.begin(); iter != fullUsageList.end(); iter++)
  555.                     {    
  556.                         CServerThread *pThread = *iter;
  557.  
  558.                         // Thread has already been locked
  559.                         long long r = pThread->m_SlQuotas[i].nBytesAllowedToTransfer - pThread->m_SlQuotas[i].nTransferred;
  560.                         if (r > 0)
  561.                         {
  562.                             if (pThread->m_SlQuotas[i].nTransferred > nThreadLimit)
  563.                                 pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  564.                             else
  565.                                 pThread->m_SlQuotas[i].nBytesAllowedToTransfer = pThread->m_SlQuotas[i].nTransferred;
  566.                             pThread->m_SlQuotas[i].nTransferred = 0;
  567.                             nRemaining -= pThread->m_SlQuotas[i].nBytesAllowedToTransfer;
  568.                         }
  569.                         else
  570.                         {
  571.                             fullUsageList2.push_back(pThread);
  572.                             // Don't unlock thread here either, do it later
  573.                             continue;
  574.                         }
  575.                         LeaveCritSection(pThread->m_threadsync);
  576.                     }
  577.                     
  578.                     if (!fullUsageList2.empty())
  579.                     {
  580.                         nThreadLimit = nRemaining / fullUsageList2.size();
  581.                         for (iter = fullUsageList2.begin(); iter != fullUsageList2.end(); iter++)
  582.                         {    
  583.                             CServerThread *pThread = *iter;
  584.                             pThread->m_SlQuotas[i].nTransferred = 0;
  585.                             pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  586.  
  587.                             // Finally unlock threads
  588.                             LeaveCritSection(pThread->m_threadsync);
  589.                         }
  590.                     }
  591.                 }
  592.             }
  593.             
  594.             LeaveCritSection(m_GlobalThreadsync);
  595.         }
  596.         ProcessNewSlQuota();
  597.     }
  598.     else if (m_pExternalIpCheck && wParam == m_pExternalIpCheck->GetTimerID())
  599.     {
  600.         EnterCritSection(m_threadsync);
  601.         m_pExternalIpCheck->OnTimer();
  602.         LeaveCritSection(m_threadsync);
  603.     }
  604.     else if (wParam == m_antiHammerTimer && m_bIsMaster)
  605.         AntiHammerDecrease();
  606. }
  607.  
  608. const int CServerThread::GetGlobalNumConnections()
  609. {
  610.     EnterCritSection(m_GlobalThreadsync);
  611.     int num=m_userids.size();
  612.     LeaveCritSection(m_GlobalThreadsync);
  613.     return num;
  614. }
  615.  
  616. CControlSocket * CServerThread::GetControlSocket(int userid)
  617. {
  618.     CControlSocket *ret=0;
  619.     EnterCritSection(m_threadsync);
  620.     std::map<int, CControlSocket *>::iterator iter=m_LocalUserIDs.find(userid);
  621.     if (iter!=m_LocalUserIDs.end())
  622.         ret=iter->second;
  623.     LeaveCritSection(m_threadsync);
  624.     return ret;
  625. }
  626.  
  627. void CServerThread::ProcessControlMessage(t_controlmessage *msg)
  628. {
  629.     if (msg->command == USERCONTROL_KICK)
  630.     {
  631.         CControlSocket *socket = GetControlSocket(msg->socketid);
  632.         if (socket)
  633.             socket->ForceClose(4);
  634.     }
  635.     delete msg;
  636. }
  637.  
  638. BOOL CServerThread::IsReady()
  639. {
  640.     return !m_bQuit;
  641. }
  642.  
  643. int CServerThread::GetIpCount(const CStdString &ip) const
  644. {
  645.     int count=0;
  646.     EnterCritSection(m_GlobalThreadsync);
  647.     std::map<CStdString, int>::iterator iter=m_userIPs.find(ip);
  648.     if (iter!=m_userIPs.end())
  649.         count=iter->second;
  650.     LeaveCritSection(m_GlobalThreadsync);
  651.     return count;
  652. }
  653.  
  654. void CServerThread::IncIpCount(const CStdString &ip)
  655. {
  656.     int count;
  657.     EnterCritSection(m_GlobalThreadsync);
  658.     std::map<CStdString, int>::iterator iter=m_userIPs.find(ip);
  659.     if (iter!=m_userIPs.end())
  660.         count=iter->second++;
  661.     else
  662.         m_userIPs[ip]=1;
  663.     LeaveCritSection(m_GlobalThreadsync);
  664. }
  665.  
  666. void CServerThread::DecIpCount(const CStdString &ip)
  667. {
  668.     EnterCritSection(m_GlobalThreadsync);
  669.     std::map<CStdString, int>::iterator iter=m_userIPs.find(ip);
  670.     ASSERT(iter!=m_userIPs.end());
  671.     if (iter==m_userIPs.end())
  672.     {
  673.         LeaveCritSection(m_GlobalThreadsync);
  674.         return;
  675.     }
  676.     else
  677.     {
  678.         ASSERT(iter->second);
  679.         if (iter->second)
  680.             iter->second--;
  681.     }
  682.     LeaveCritSection(m_GlobalThreadsync);
  683. }
  684.  
  685. void CServerThread::IncSendCount(int count)
  686. {
  687.     m_nSendCount += count;
  688. }
  689.  
  690. void CServerThread::IncRecvCount(int count)
  691. {
  692.     m_nRecvCount += count;
  693. }
  694.  
  695. void CServerThread::ProcessNewSlQuota()
  696. {
  697.     EnterCritSection(m_threadsync);
  698.  
  699.     std::map<int, CControlSocket *>::iterator iter;
  700.  
  701.     for (int i = 0; i < 2; i++)
  702.     {
  703.         if (m_SlQuotas[i].nBytesAllowedToTransfer == -1)
  704.         {
  705.             for (iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  706.             {
  707.                 CControlSocket *pControlSocket = iter->second;
  708.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = -1;
  709.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  710.             }
  711.             continue;
  712.         }
  713.     
  714.         long long nRemaining = m_SlQuotas[i].nBytesAllowedToTransfer;
  715.         long long nThreadLimit = nRemaining / m_sInstanceList.size();
  716.             
  717.         std::list<CControlSocket *> fullUsageList;
  718.         
  719.         for (iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  720.         {
  721.             CControlSocket *pControlSocket = iter->second;
  722.             long long r = pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer - pControlSocket->m_SlQuotas[i].nTransferred;
  723.             if (pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer == -1)
  724.             {
  725.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  726.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  727.             }
  728.             else if (r > 0 && pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer <= nThreadLimit)
  729.             {
  730.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  731.                 nRemaining -= pControlSocket->m_SlQuotas[i].nTransferred;
  732.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  733.             }
  734.             else if (r > 0 && pControlSocket->m_SlQuotas[i].nTransferred < nThreadLimit)
  735.             {
  736.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  737.                 nRemaining -= pControlSocket->m_SlQuotas[i].nTransferred;
  738.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  739.             }
  740.             else
  741.             {
  742.                 fullUsageList.push_back(pControlSocket);
  743.                 continue;
  744.             }
  745.         }
  746.         
  747.         std::list<CControlSocket *> fullUsageList2;
  748.         if (!fullUsageList.empty())
  749.         {
  750.             std::list<CControlSocket *>::iterator iter;
  751.             
  752.             nThreadLimit = nRemaining / fullUsageList.size();
  753.             for (iter = fullUsageList.begin(); iter != fullUsageList.end(); iter++)
  754.             {    
  755.                 CControlSocket *pControlSocket = *iter;
  756.                 long long r = pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer - pControlSocket->m_SlQuotas[i].nTransferred;
  757.                 if (r)
  758.                 {
  759.                     if (pControlSocket->m_SlQuotas[i].nTransferred > nThreadLimit)
  760.                         pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  761.                     else
  762.                         pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = pControlSocket->m_SlQuotas[i].nTransferred;
  763.                     pControlSocket->m_SlQuotas[i].nTransferred = 0;
  764.                     nRemaining -= pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer;
  765.                 }
  766.                 else
  767.                 {
  768.                     fullUsageList2.push_back(pControlSocket);
  769.                     continue;
  770.                 }
  771.             }
  772.             
  773.             if (!fullUsageList2.empty())
  774.             {
  775.                 nThreadLimit = nRemaining / fullUsageList2.size();
  776.                 for (iter = fullUsageList2.begin(); iter != fullUsageList2.end(); iter++)
  777.                 {    
  778.                     CControlSocket *pControlSocket = *iter;
  779.                     pControlSocket->m_SlQuotas[i].nTransferred = 0;
  780.                     pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  781.                 }
  782.             }
  783.         }
  784.     }
  785.     
  786.     for (iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  787.     {
  788.         CControlSocket *pControlSocket = iter->second;
  789.         pControlSocket->Continue();
  790.     }
  791.  
  792.     LeaveCritSection(m_threadsync);
  793. }
  794.  
  795. void CServerThread::GatherTransferedBytes()
  796. {
  797.     EnterCritSection(m_threadsync);
  798.     for (std::map<int, CControlSocket *>::iterator iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  799.     {
  800.         for (int i = 0; i < 2; i++)
  801.         {
  802.             if (iter->second->m_SlQuotas[i].nBytesAllowedToTransfer != -1)
  803.                 if (iter->second->m_SlQuotas[i].bBypassed)
  804.                     iter->second->m_SlQuotas[i].nTransferred = 0;
  805.                 else
  806.                     m_SlQuotas[i].nTransferred += iter->second->m_SlQuotas[i].nTransferred;
  807.  
  808.             iter->second->m_SlQuotas[i].bBypassed = false;
  809.         }
  810.     }
  811.     LeaveCritSection(m_threadsync);
  812. }
  813.  
  814. CStdString CServerThread::GetExternalIP(const CStdString& localIP)
  815. {
  816.     CStdString ip;
  817.     EnterCritSection(m_threadsync);
  818.     if (m_pExternalIpCheck)
  819.     {
  820.         ip = m_pExternalIpCheck->GetIP(localIP);
  821.         LeaveCritSection(m_threadsync);
  822.     }
  823.     else
  824.     {
  825.         LeaveCritSection(m_threadsync);
  826.         EnterCritSection(m_GlobalThreadsync);
  827.         CServerThread *pThread = m_sInstanceList.front();
  828.         EnterCritSection(pThread->m_threadsync);
  829.         if (pThread != this && pThread->m_pExternalIpCheck)
  830.             ip = pThread->m_pExternalIpCheck->GetIP(localIP);
  831.         LeaveCritSection(pThread->m_threadsync);
  832.         LeaveCritSection(m_GlobalThreadsync);
  833.     }
  834.  
  835.     return ip;
  836. }
  837.  
  838. void CServerThread::ExternalIPFailed()
  839. {
  840.     CStdString ip;
  841.     EnterCritSection(m_threadsync);
  842.     if (m_pExternalIpCheck)
  843.     {
  844.         m_pExternalIpCheck->TriggerUpdate();
  845.         LeaveCritSection(m_threadsync);
  846.     }
  847.     else
  848.     {
  849.         LeaveCritSection(m_threadsync);
  850.         EnterCritSection(m_GlobalThreadsync);
  851.         CServerThread *pThread = m_sInstanceList.front();
  852.         EnterCritSection(pThread->m_threadsync);
  853.         if (pThread != this && pThread->m_pExternalIpCheck)
  854.             pThread->m_pExternalIpCheck->TriggerUpdate();
  855.         LeaveCritSection(pThread->m_threadsync);
  856.         LeaveCritSection(m_GlobalThreadsync);
  857.     }
  858. }
  859.  
  860. void CServerThread::SendNotification(WPARAM wParam, LPARAM lParam)
  861. {
  862.     EnterCritSection(m_threadsync);
  863.     t_Notification notification;
  864.     notification.wParam = wParam;
  865.     notification.lParam = lParam;
  866.  
  867.     if (m_pendingNotifications.empty())
  868.         PostMessage(hMainWnd, m_nNotificationMessageId, 0, 0);
  869.  
  870.     m_pendingNotifications.push_back(notification);
  871.  
  872.     // Check if main thread can't handle number of notifications fast enough, throttle thread if neccessary
  873.     if (m_pendingNotifications.size() > 200 && m_throttled < 3)
  874.     {
  875.         SetPriority(THREAD_PRIORITY_IDLE);
  876.         m_throttled = 3;
  877.     }
  878.     else if (m_pendingNotifications.size() > 150 && m_throttled < 2)
  879.     {
  880.         SetPriority(THREAD_PRIORITY_LOWEST);
  881.         m_throttled = 2;
  882.     }
  883.     else if (m_pendingNotifications.size() > 100 && !m_throttled)
  884.     {
  885.         SetPriority(THREAD_PRIORITY_BELOW_NORMAL);
  886.         m_throttled = 1;
  887.     }
  888.     
  889.     LeaveCritSection(m_threadsync);
  890. }
  891.  
  892. void CServerThread::GetNotifications(std::list<CServerThread::t_Notification>& list)
  893. {
  894.     EnterCritSection(m_threadsync);
  895.  
  896.     m_pendingNotifications.swap(list);
  897.  
  898.     if (m_throttled)
  899.         SetPriority(THREAD_PRIORITY_NORMAL);
  900.  
  901.     LeaveCritSection(m_threadsync);
  902. }
  903.  
  904. void CServerThread::AntiHammerIncrease(const CStdString& ip)
  905. {
  906.     EnterCritSection(m_GlobalThreadsync);
  907.  
  908.     std::map<CStdString, int>::iterator iter = m_antiHammerInfo.find(ip);
  909.     if (iter != m_antiHammerInfo.end())
  910.     {
  911.         if (iter->second < 20)
  912.             iter->second++;
  913.         LeaveCritSection(m_GlobalThreadsync);
  914.         return;
  915.     }
  916.     if (m_antiHammerInfo.size() >= 1000)
  917.     {
  918.         std::map<CStdString, int>::iterator best = m_antiHammerInfo.begin();
  919.         for (iter = m_antiHammerInfo.begin(); iter != m_antiHammerInfo.end(); iter++)
  920.         {
  921.             if (iter->second < best->second)
  922.                 best = iter;
  923.         }
  924.         m_antiHammerInfo.erase(best);
  925.     }
  926.     m_antiHammerInfo.insert(std::make_pair(ip, 1));
  927.  
  928.     LeaveCritSection(m_GlobalThreadsync);
  929. }
  930.  
  931. void CServerThread::AntiHammerDecrease()
  932. {
  933.     EnterCritSection(m_GlobalThreadsync);
  934.  
  935.     std::map<CStdString, int>::iterator iter = m_antiHammerInfo.begin();
  936.     while (iter != m_antiHammerInfo.end())
  937.     {
  938.         if (iter->second > 1)
  939.         {
  940.             --(iter->second);
  941.             ++iter;
  942.         }
  943.         else
  944.             m_antiHammerInfo.erase(iter++);
  945.     }
  946.     
  947.     LeaveCritSection(m_GlobalThreadsync);
  948. }
  949.  
  950. CHashThread& CServerThread::GetHashThread()
  951. {
  952.     return *m_hashThread;
  953. }
  954.